﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using BasicFramework.Helper;
using BasicFramework.Scenes;

namespace BasicFramework.Factory
{
    public class SceneFactory : Factory
    {
        SceneManager manager;

        public SceneFactory(SceneManager manager)
        {
            Logger.Info("Initialize SceneFactory");
            this.manager = manager;
            Logger.Info("SceneFactory initialized");
        }

        public T Create<T>(string name) where T : Scene
        {
            Logger.Info("Creating " + name + " scene");
            // if we didn't pass an object array, we would enter an infinite recursive loop
            // since we would essentially be calling this method, which then calls this method.. etc.
            // where we actually wanted to call the method overload taking an object[] parameter list
            return Create<T>(new object[] { name });
        }

        public T Create<T>(string name, Guid guid) where T : Scene
        {
            Logger.Info("Creating " + name + " scene");
            return Create<T>(new object[] { name, guid });
        }

        // all the code inside this method could be replaced by 1 line, if the CF hadn't stripped System.Activator down to a bare minimum
        private T Create<T>(params object[] parameters) where T : Scene
        {
            
            ConstructorInfo bestMatch = GetBestMatchingConstructor(typeof(T), parameters);

            object obj = null;

            try
            {
                obj = bestMatch.Invoke(parameters);
            }
            catch (TargetInvocationException)
            {
                throw;
            }
            catch (TargetParameterCountException)
            {
                throw;
            }

            Scene scene = obj as Scene;

            manager.Add(scene);

            Logger.Info(scene.Name + " scene successfully created");
            return obj as T;
        }
    }


}
